home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / glibc108.gz / glibc108 / glibc-1.08.1 / sunrpc / xdr.c < prev   
C/C++ Source or Header  |  1994-02-06  |  11KB  |  578 lines

  1. /* @(#)xdr.c    2.1 88/07/29 4.0 RPCSRC */
  2. /*
  3.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  4.  * unrestricted use provided that this legend is included on all tape
  5.  * media and as a part of the software program in whole or part.  Users
  6.  * may copy or modify Sun RPC without charge, but are not authorized
  7.  * to license or distribute it to anyone else except as part of a product or
  8.  * program developed by the user.
  9.  * 
  10.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  11.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  12.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  13.  * 
  14.  * Sun RPC is provided with no support and without any obligation on the
  15.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  16.  * modification or enhancement.
  17.  * 
  18.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  19.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  20.  * OR ANY PART THEREOF.
  21.  * 
  22.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  23.  * or profits or other special, indirect and consequential damages, even if
  24.  * Sun has been advised of the possibility of such damages.
  25.  * 
  26.  * Sun Microsystems, Inc.
  27.  * 2550 Garcia Avenue
  28.  * Mountain View, California  94043
  29.  */
  30. #if !defined(lint) && defined(SCCSIDS)
  31. static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
  32. #endif
  33.  
  34. /*
  35.  * xdr.c, Generic XDR routines implementation.
  36.  *
  37.  * Copyright (C) 1986, Sun Microsystems, Inc.
  38.  *
  39.  * These are the "generic" xdr routines used to serialize and de-serialize
  40.  * most common data items.  See xdr.h for more info on the interface to
  41.  * xdr.
  42.  */
  43.  
  44. #include <stdio.h>
  45. char *malloc();
  46.  
  47. #include <rpc/types.h>
  48. #include <rpc/xdr.h>
  49.  
  50. /*
  51.  * constants specific to the xdr "protocol"
  52.  */
  53. #define XDR_FALSE    ((long) 0)
  54. #define XDR_TRUE    ((long) 1)
  55. #define LASTUNSIGNED    ((u_int) 0-1)
  56.  
  57. /*
  58.  * for unit alignment
  59.  */
  60. static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
  61.  
  62. /*
  63.  * Free a data structure using XDR
  64.  * Not a filter, but a convenient utility nonetheless
  65.  */
  66. void
  67. xdr_free(proc, objp)
  68.     xdrproc_t proc;
  69.     char *objp;
  70. {
  71.     XDR x;
  72.     
  73.     x.x_op = XDR_FREE;
  74.     (*proc)(&x, objp);
  75. }
  76.  
  77. /*
  78.  * XDR nothing
  79.  */
  80. bool_t
  81. xdr_void(/* xdrs, addr */)
  82.     /* XDR *xdrs; */
  83.     /* caddr_t addr; */
  84. {
  85.  
  86.     return (TRUE);
  87. }
  88.  
  89. /*
  90.  * XDR integers
  91.  */
  92. bool_t
  93. xdr_int(xdrs, ip)
  94.     XDR *xdrs;
  95.     int *ip;
  96. {
  97.  
  98. #ifdef lint
  99.     (void) (xdr_short(xdrs, (short *)ip));
  100.     return (xdr_long(xdrs, (long *)ip));
  101. #else
  102.     if (sizeof (int) == sizeof (long)) {
  103.         return (xdr_long(xdrs, (long *)ip));
  104.     } else {
  105.         return (xdr_short(xdrs, (short *)ip));
  106.     }
  107. #endif
  108. }
  109.  
  110. /*
  111.  * XDR unsigned integers
  112.  */
  113. bool_t
  114. xdr_u_int(xdrs, up)
  115.     XDR *xdrs;
  116.     u_int *up;
  117. {
  118.  
  119. #ifdef lint
  120.     (void) (xdr_short(xdrs, (short *)up));
  121.     return (xdr_u_long(xdrs, (u_long *)up));
  122. #else
  123.     if (sizeof (u_int) == sizeof (u_long)) {
  124.         return (xdr_u_long(xdrs, (u_long *)up));
  125.     } else {
  126.         return (xdr_short(xdrs, (short *)up));
  127.     }
  128. #endif
  129. }
  130.  
  131. /*
  132.  * XDR long integers
  133.  * same as xdr_u_long - open coded to save a proc call!
  134.  */
  135. bool_t
  136. xdr_long(xdrs, lp)
  137.     register XDR *xdrs;
  138.     long *lp;
  139. {
  140.  
  141.     if (xdrs->x_op == XDR_ENCODE)
  142.         return (XDR_PUTLONG(xdrs, lp));
  143.  
  144.     if (xdrs->x_op == XDR_DECODE)
  145.         return (XDR_GETLONG(xdrs, lp));
  146.  
  147.     if (xdrs->x_op == XDR_FREE)
  148.         return (TRUE);
  149.  
  150.     return (FALSE);
  151. }
  152.  
  153. /*
  154.  * XDR unsigned long integers
  155.  * same as xdr_long - open coded to save a proc call!
  156.  */
  157. bool_t
  158. xdr_u_long(xdrs, ulp)
  159.     register XDR *xdrs;
  160.     u_long *ulp;
  161. {
  162.  
  163.     if (xdrs->x_op == XDR_DECODE)
  164.         return (XDR_GETLONG(xdrs, (long *)ulp));
  165.     if (xdrs->x_op == XDR_ENCODE)
  166.         return (XDR_PUTLONG(xdrs, (long *)ulp));
  167.     if (xdrs->x_op == XDR_FREE)
  168.         return (TRUE);
  169.     return (FALSE);
  170. }
  171.  
  172. /*
  173.  * XDR short integers
  174.  */
  175. bool_t
  176. xdr_short(xdrs, sp)
  177.     register XDR *xdrs;
  178.     short *sp;
  179. {
  180.     long l;
  181.  
  182.     switch (xdrs->x_op) {
  183.  
  184.     case XDR_ENCODE:
  185.         l = (long) *sp;
  186.         return (XDR_PUTLONG(xdrs, &l));
  187.  
  188.     case XDR_DECODE:
  189.         if (!XDR_GETLONG(xdrs, &l)) {
  190.             return (FALSE);
  191.         }
  192.         *sp = (short) l;
  193.         return (TRUE);
  194.  
  195.     case XDR_FREE:
  196.         return (TRUE);
  197.     }
  198.     return (FALSE);
  199. }
  200.  
  201. /*
  202.  * XDR unsigned short integers
  203.  */
  204. bool_t
  205. xdr_u_short(xdrs, usp)
  206.     register XDR *xdrs;
  207.     u_short *usp;
  208. {
  209.     u_long l;
  210.  
  211.     switch (xdrs->x_op) {
  212.  
  213.     case XDR_ENCODE:
  214.         l = (u_long) *usp;
  215.         return (XDR_PUTLONG(xdrs, &l));
  216.  
  217.     case XDR_DECODE:
  218.         if (!XDR_GETLONG(xdrs, &l)) {
  219.             return (FALSE);
  220.         }
  221.         *usp = (u_short) l;
  222.         return (TRUE);
  223.  
  224.     case XDR_FREE:
  225.         return (TRUE);
  226.     }
  227.     return (FALSE);
  228. }
  229.  
  230.  
  231. /*
  232.  * XDR a char
  233.  */
  234. bool_t
  235. xdr_char(xdrs, cp)
  236.     XDR *xdrs;
  237.     char *cp;
  238. {
  239.     int i;
  240.  
  241.     i = (*cp);
  242.     if (!xdr_int(xdrs, &i)) {
  243.         return (FALSE);
  244.     }
  245.     *cp = i;
  246.     return (TRUE);
  247. }
  248.  
  249. /*
  250.  * XDR an unsigned char
  251.  */
  252. bool_t
  253. xdr_u_char(xdrs, cp)
  254.     XDR *xdrs;
  255.     char *cp;
  256. {
  257.     u_int u;
  258.  
  259.     u = (*cp);
  260.     if (!xdr_u_int(xdrs, &u)) {
  261.         return (FALSE);
  262.     }
  263.     *cp = u;
  264.     return (TRUE);
  265. }
  266.  
  267. /*
  268.  * XDR booleans
  269.  */
  270. bool_t
  271. xdr_bool(xdrs, bp)
  272.     register XDR *xdrs;
  273.     bool_t *bp;
  274. {
  275.     long lb;
  276.  
  277.     switch (xdrs->x_op) {
  278.  
  279.     case XDR_ENCODE:
  280.         lb = *bp ? XDR_TRUE : XDR_FALSE;
  281.         return (XDR_PUTLONG(xdrs, &lb));
  282.  
  283.     case XDR_DECODE:
  284.         if (!XDR_GETLONG(xdrs, &lb)) {
  285.             return (FALSE);
  286.         }
  287.         *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  288.         return (TRUE);
  289.  
  290.     case XDR_FREE:
  291.         return (TRUE);
  292.     }
  293.     return (FALSE);
  294. }
  295.  
  296. /*
  297.  * XDR enumerations
  298.  */
  299. bool_t
  300. xdr_enum(xdrs, ep)
  301.     XDR *xdrs;
  302.     enum_t *ep;
  303. {
  304. #ifndef lint
  305.     enum sizecheck { SIZEVAL };    /* used to find the size of an enum */
  306.  
  307.     /*
  308.      * enums are treated as ints
  309.      */
  310.     if (sizeof (enum sizecheck) == sizeof (long)) {
  311.         return (xdr_long(xdrs, (long *)ep));
  312.     } else if (sizeof (enum sizecheck) == sizeof (short)) {
  313.         return (xdr_short(xdrs, (short *)ep));
  314.     } else {
  315.         return (FALSE);
  316.     }
  317. #else
  318.     (void) (xdr_short(xdrs, (short *)ep));
  319.     return (xdr_long(xdrs, (long *)ep));
  320. #endif
  321. }
  322.  
  323. /*
  324.  * XDR opaque data
  325.  * Allows the specification of a fixed size sequence of opaque bytes.
  326.  * cp points to the opaque object and cnt gives the byte length.
  327.  */
  328. bool_t
  329. xdr_opaque(xdrs, cp, cnt)
  330.     register XDR *xdrs;
  331.     caddr_t cp;
  332.     register u_int cnt;
  333. {
  334.     register u_int rndup;
  335.     static crud[BYTES_PER_XDR_UNIT];
  336.  
  337.     /*
  338.      * if no data we are done
  339.      */
  340.     if (cnt == 0)
  341.         return (TRUE);
  342.  
  343.     /*
  344.      * round byte count to full xdr units
  345.      */
  346.     rndup = cnt % BYTES_PER_XDR_UNIT;
  347.     if (rndup > 0)
  348.         rndup = BYTES_PER_XDR_UNIT - rndup;
  349.  
  350.     if (xdrs->x_op == XDR_DECODE) {
  351.         if (!XDR_GETBYTES(xdrs, cp, cnt)) {
  352.             return (FALSE);
  353.         }
  354.         if (rndup == 0)
  355.             return (TRUE);
  356.         return (XDR_GETBYTES(xdrs, crud, rndup));
  357.     }
  358.  
  359.     if (xdrs->x_op == XDR_ENCODE) {
  360.         if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
  361.             return (FALSE);
  362.         }
  363.         if (rndup == 0)
  364.             return (TRUE);
  365.         return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
  366.     }
  367.  
  368.     if (xdrs->x_op == XDR_FREE) {
  369.         return (TRUE);
  370.     }
  371.  
  372.     return (FALSE);
  373. }
  374.  
  375. /*
  376.  * XDR counted bytes
  377.  * *cpp is a pointer to the bytes, *sizep is the count.
  378.  * If *cpp is NULL maxsize bytes are allocated
  379.  */
  380. bool_t
  381. xdr_bytes(xdrs, cpp, sizep, maxsize)
  382.     register XDR *xdrs;
  383.     char **cpp;
  384.     register u_int *sizep;
  385.     u_int maxsize;
  386. {
  387.     register char *sp = *cpp;  /* sp is the actual string pointer */
  388.     register u_int nodesize;
  389.  
  390.     /*
  391.      * first deal with the length since xdr bytes are counted
  392.      */
  393.     if (! xdr_u_int(xdrs, sizep)) {
  394.         return (FALSE);
  395.     }
  396.     nodesize = *sizep;
  397.     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
  398.         return (FALSE);
  399.     }
  400.  
  401.     /*
  402.      * now deal with the actual bytes
  403.      */
  404.     switch (xdrs->x_op) {
  405.  
  406.     case XDR_DECODE:
  407.         if (nodesize == 0) {
  408.             return (TRUE);
  409.         }
  410.         if (sp == NULL) {
  411.             *cpp = sp = (char *)mem_alloc(nodesize);
  412.         }
  413.         if (sp == NULL) {
  414.             (void) fprintf(stderr, "xdr_bytes: out of memory\n");
  415.             return (FALSE);
  416.         }
  417.         /* fall into ... */
  418.  
  419.     case XDR_ENCODE:
  420.         return (xdr_opaque(xdrs, sp, nodesize));
  421.  
  422.     case XDR_FREE:
  423.         if (sp != NULL) {
  424.             mem_free(sp, nodesize);
  425.             *cpp = NULL;
  426.         }
  427.         return (TRUE);
  428.     }
  429.     return (FALSE);
  430. }
  431.  
  432. /*
  433.  * Implemented here due to commonality of the object.
  434.  */
  435. bool_t
  436. xdr_netobj(xdrs, np)
  437.     XDR *xdrs;
  438.     struct netobj *np;
  439. {
  440.  
  441.     return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
  442. }
  443.  
  444. /*
  445.  * XDR a descriminated union
  446.  * Support routine for discriminated unions.
  447.  * You create an array of xdrdiscrim structures, terminated with
  448.  * an entry with a null procedure pointer.  The routine gets
  449.  * the discriminant value and then searches the array of xdrdiscrims
  450.  * looking for that value.  It calls the procedure given in the xdrdiscrim
  451.  * to handle the discriminant.  If there is no specific routine a default
  452.  * routine may be called.
  453.  * If there is no specific or default routine an error is returned.
  454.  */
  455. bool_t
  456. xdr_union(xdrs, dscmp, unp, choices, dfault)
  457.     register XDR *xdrs;
  458.     enum_t *dscmp;        /* enum to decide which arm to work on */
  459.     char *unp;        /* the union itself */
  460.     struct xdr_discrim *choices;    /* [value, xdr proc] for each arm */
  461.     xdrproc_t dfault;    /* default xdr routine */
  462. {
  463.     register enum_t dscm;
  464.  
  465.     /*
  466.      * we deal with the discriminator;  it's an enum
  467.      */
  468.     if (! xdr_enum(xdrs, dscmp)) {
  469.         return (FALSE);
  470.     }
  471.     dscm = *dscmp;
  472.  
  473.     /*
  474.      * search choices for a value that matches the discriminator.
  475.      * if we find one, execute the xdr routine for that value.
  476.      */
  477.     for (; choices->proc != NULL_xdrproc_t; choices++) {
  478.         if (choices->value == dscm)
  479.             return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
  480.     }
  481.  
  482.     /*
  483.      * no match - execute the default xdr routine if there is one
  484.      */
  485.     return ((dfault == NULL_xdrproc_t) ? FALSE :
  486.         (*dfault)(xdrs, unp, LASTUNSIGNED));
  487. }
  488.  
  489.  
  490. /*
  491.  * Non-portable xdr primitives.
  492.  * Care should be taken when moving these routines to new architectures.
  493.  */
  494.  
  495.  
  496. /*
  497.  * XDR null terminated ASCII strings
  498.  * xdr_string deals with "C strings" - arrays of bytes that are
  499.  * terminated by a NULL character.  The parameter cpp references a
  500.  * pointer to storage; If the pointer is null, then the necessary
  501.  * storage is allocated.  The last parameter is the max allowed length
  502.  * of the string as specified by a protocol.
  503.  */
  504. bool_t
  505. xdr_string(xdrs, cpp, maxsize)
  506.     register XDR *xdrs;
  507.     char **cpp;
  508.     u_int maxsize;
  509. {
  510.     register char *sp = *cpp;  /* sp is the actual string pointer */
  511.     u_int size;
  512.     u_int nodesize;
  513.  
  514.     /*
  515.      * first deal with the length since xdr strings are counted-strings
  516.      */
  517.     switch (xdrs->x_op) {
  518.     case XDR_FREE:
  519.         if (sp == NULL) {
  520.             return(TRUE);    /* already free */
  521.         }
  522.         /* fall through... */
  523.     case XDR_ENCODE:
  524.         size = strlen(sp);
  525.         break;
  526.     }
  527.     if (! xdr_u_int(xdrs, &size)) {
  528.         return (FALSE);
  529.     }
  530.     if (size > maxsize) {
  531.         return (FALSE);
  532.     }
  533.     nodesize = size + 1;
  534.  
  535.     /*
  536.      * now deal with the actual bytes
  537.      */
  538.     switch (xdrs->x_op) {
  539.  
  540.     case XDR_DECODE:
  541.         if (nodesize == 0) {
  542.             return (TRUE);
  543.         }
  544.         if (sp == NULL)
  545.             *cpp = sp = (char *)mem_alloc(nodesize);
  546.         if (sp == NULL) {
  547.             (void) fprintf(stderr, "xdr_string: out of memory\n");
  548.             return (FALSE);
  549.         }
  550.         sp[size] = 0;
  551.         /* fall into ... */
  552.  
  553.     case XDR_ENCODE:
  554.         return (xdr_opaque(xdrs, sp, size));
  555.  
  556.     case XDR_FREE:
  557.         mem_free(sp, nodesize);
  558.         *cpp = NULL;
  559.         return (TRUE);
  560.     }
  561.     return (FALSE);
  562. }
  563.  
  564. /* 
  565.  * Wrapper for xdr_string that can be called directly from 
  566.  * routines like clnt_call
  567.  */
  568. bool_t
  569. xdr_wrapstring(xdrs, cpp)
  570.     XDR *xdrs;
  571.     char **cpp;
  572. {
  573.     if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
  574.         return (TRUE);
  575.     }
  576.     return (FALSE);
  577. }
  578.